iThome 鐵人賽 30天今天要處理的是讓每個頁面都有自己的Container來包裝排版,畢竟每個頁面的排版不一定都相同,這個專案主要就兩個頁面,首頁及標記編輯頁面,兩個預想的排版差異滿大的,所以就選擇分開裝囉!
那就先來做首頁的Container吧!
先在/src/components裡新增main資料夾,這個資料夾我打算把主要畫面呈現的component集中放置在內。再來在main內新增HomePage.jsx。
之後就是開始調版面時間啦,就大概調到自己覺得看得下去的地步,當然對自己有美觀的要求就加油吧,我先放棄XD,大概調個間距就好~
這是我最終調整完的版本:HomePage.jsx:
import React, { useState, useEffect } from 'react'
import { Box } from '@mui/material'
import VideoCard from '../VideoCard'
export default function HomePage() {
    return (
        <Box sx={{ p: 3, display: "flex", flexWrap: "wrap", justifyContent: "center" }}>
             <VideoCard
                v={"Ga22mpTDS6A"}
                title={"東京版《Joe是要對決》日幣30000元的奢華壽喜燒對決日幣600元的平價壽喜燒!Ep127@徐海莉 Hailey@流川莉蘿 Rilo ch."}
            />
            <VideoCard
                v={"SxQgIJ3rQ3c"}
                title={"NEAL對決秋天的王者李宰赫!Royal Roader再度誕生!個人賽決賽SET 2《2022 跑跑卡丁車聯賽 S2》"}
            />
        </Box>
    )
}
VideoCard.jsx:
import React from 'react'
import { Card, CardMedia, CardContent, Typography } from '@mui/material'
import { Link } from 'react-router-dom' // 導入Link
export default function VideoCard(props) {
  const { v, title } = props
  return (
    <Card sx={{ maxWidth: 480, m: 1 }}>
      <Link className='reset' to={`/watch?v=${v}`}>
        <CardMedia
          component="img"
          // height="360"
          image={`https://img.youtube.com/vi/${v}/hqdefault.jpg`}
          alt="green iguana"
        />
        <CardContent>
          <Typography gutterBottom variant="h5" component="div" className='twoline'>
            {title}
          </Typography>
        </CardContent>
      </Link>
    </Card>
  )
}
新增的CSS (為了把Link產生的超連結變色和hover拿掉):
.reset{
  text-decoration: none;
  color: #000;
  outline: none;
}
先看看上面的HomePage.jsx,可以發現目前卡片還都是寫死的情況,接下來會模擬API已經取得資料後,當作參數傳進去的方式去用mapping讓卡片渲染出來。
因為要取得資料的時間點會是在訪問HomePage的時候,所以把模擬的data放在HomePage中:
import React, { useState, useEffect } from 'react'
import { Box } from '@mui/material'
import VideoCard from '../VideoCard'
export default function HomePage() {
    const [data, setData] = useState(null)
    useEffect(() => {
        // 第一次進入HomePage.jsx時去取得資料
        getData()
    }, [])
    const getData = () => {
        // 模擬API取得資料
        setData(
            [
                { v: "Ga22mpTDS6A", title: "東京版《Joe是要對決》日幣30000元的奢華壽喜燒對決日幣600元的平價壽喜燒!Ep127@徐海莉 Hailey@流川莉蘿 Rilo ch." },
                { v: "SxQgIJ3rQ3c", title: "NEAL對決秋天的王者李宰赫!Royal Roader再度誕生!個人賽決賽SET 2《2022 跑跑卡丁車聯賽 S2》" }
            ]
        )
    }
    return (
        <Box sx={{ p: 3, display: "flex", flexWrap: "wrap", justifyContent: "center" }}>
            {/** 用.map的方式把array的資料一個一個渲染出來 */}
            {!!data && data.map(d =>
                <VideoCard
                    // key用來幫助React分辨哪些項目被改變、增加或刪除
                    key={d.v}
                    v={d.v}
                    title={d.title}
                />
            )}
        </Box>
    )
}
在mapping中有個重點,就是如果是mapping component的話要記得在component裡加入key參數,並給予一個在這個陣列裡不會重複出現的值。
當然如果裡面的元素不會變動的話有個偷懶的方法,但是不建議使用:
{!!data && data.map((d, index) =>
    <VideoCard
        key={index}
        v={d.v}
        title={d.title}
    />
)}
偷懶的方法藏在map的第二個參數裡,index代表是array的第幾個值 (從0開始),所以一定是唯一的,但並不推薦使用在會改變順序的情況,可能會發生意想不到的錯誤。

可以發現array的資料成功變出來了。
當然我們也可以模擬資料很多的情況,看看會變甚麼樣子吧!

整理完後版面是不是看起來清爽很多了呢?再來就是處理編輯頁面啦~不過居然剩下10天了,時間過得好快,開始擔心結束的時候還沒講完了...?
附上專案:2022-iThomeIronman
對資安或Mapbox有興趣的話也可以觀看我們團隊的鐵人發文喔~